﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;

namespace AssemblyInfo
{
    public class AssemblyInfo : MarshalByRefObject
    {
        public AssemblyInfo(string file)
        {
            File = file;
            IsEditAndContinueEnabled = false;
            IsIgnoreSymbolStoreSequencePoints = false;
            IsJitOptimized = false;
            IsJitTrackingEnabled = false;
        }

        public string File { get; private set; }

        public bool IsJitTrackingEnabled { get; set; }

        public bool IsJitOptimized { get; set; }

        public bool IsIgnoreSymbolStoreSequencePoints { get; set; }

        public bool IsEditAndContinueEnabled { get; set; }
    }

    public class AssemblyInfoLoader : MarshalByRefObject
    {
        public List<AssemblyInfo> LoadAssemblyInfo(params  string[] files)
        {
            List<AssemblyInfo> result = new List<AssemblyInfo>();

            foreach (var file in files)
            {
                Assembly assembly = Assembly.LoadFrom(file);

                AssemblyInfo assemblyInfo = new AssemblyInfo(file);
                DebuggableAttribute debugAttribute = GetDebuggableAttribute(assembly);
                if (debugAttribute != null)
                {
                    assemblyInfo.IsJitTrackingEnabled = debugAttribute.IsJITTrackingEnabled;
                    assemblyInfo.IsJitOptimized = !debugAttribute.IsJITOptimizerDisabled;
                    assemblyInfo.IsIgnoreSymbolStoreSequencePoints = (debugAttribute.DebuggingFlags & DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints) != DebuggableAttribute.DebuggingModes.None;
                    assemblyInfo.IsEditAndContinueEnabled = (debugAttribute.DebuggingFlags & DebuggableAttribute.DebuggingModes.EnableEditAndContinue) != DebuggableAttribute.DebuggingModes.None;
                }
                else
                {
                    assemblyInfo.IsJitTrackingEnabled = false;
                    assemblyInfo.IsJitOptimized = true;
                    assemblyInfo.IsIgnoreSymbolStoreSequencePoints = false;
                    assemblyInfo.IsEditAndContinueEnabled = false;
                }

                result.Add(assemblyInfo);
            }

            return result;
        }

        private DebuggableAttribute GetDebuggableAttribute(Assembly assemb)
        {
            if (assemb == null) throw new ArgumentNullException("assemb");

            return assemb.GetCustomAttributes(false).OfType<DebuggableAttribute>().Select(att => att as DebuggableAttribute).FirstOrDefault();
        }
    }
}
